// 这里面存放的就是 vuex 相关的核心代码
import Vue from 'vue'
import Vuex from 'vuex'

import user from './modules/user'
import setting from './modules/setting'

// 插件安装
Vue.use(Vuex)

// 创建仓库
const store = new Vuex.Store({
  // 1 通过state可以提供数据 state 状态, 即数据, 类似于vue组件中的data,
  // 区别:
  //   1.data 是组件自己的数据,
  //   2.state 中的数据整个vue项目的组件都能访问到
  state: {
    title: '大标题',
    count: 101,
    list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  },
  // 2 通过mutations可以提供修改数据的方法
  mutations: {
    // 所有mutations的函数 第一个参数都是state
    addCount (state) {
      // 修改数据 - 在组件里面通过commit提交
      state.count += 1
    },
    addFive (state) {
      // 修改数据 - 在组件里面通过commit提交
      state.count += 5
    },
    changeTitle (state) {
      state.title = '小标题'
    },
    handleAddWithParam (state, n) {
      // 修改数据 - 在组件里面通过commit提交
      state.count += n
    },
    changeTitleWithParam (state, input1) {
      state.title = input1
    },
    handleSubWithParam (state, n) {
      state.count -= n
    },
    changeCount (state, newVal) {
      state.count = newVal
    }
  },
  // 3 actions处理异步
  // 注意不能直接操作state 操作state还是需要commit mutation
  actions: {
    // context 上下文 (此处未分模块，可以当成store仓库)
    // context.commit(mutation名字 ，额外参数)
    changeCountAsync (context, num) {
      // 这里是setTimeout模拟异步，以后大部分场景是发请求
      setTimeout(() => {
        context.commit('changeCount', num)
      }, 1000)
    }
  },
  // 4 getters 类似于计算属性
  getters: {
    // 注意点:
    // 1.形参第一个参数，就是state
    // 2.必须有返回值，返回值就是getters的值
    filterList (state) {
      return state.list.filter(item => item > 5)
    }
  },
  // 5 modules模块
  modules: {
    user, setting
  }
})

/*
核心概念 - 模块 module (进阶语法)
  目标:掌握核心概念module模块的创建
  由于vuex使用单一状态树，应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时
  store对象就有可能变得相当臃肿。(当项目变得越来越大的时候，Vuex会变得越来越难以维护)

  模块拆分:
    1. user模块文件: store/modules/user.js
      const state = {
        userInfo: {
          name : 'zs',
          age: 18,
        }
      }
      const mutations = {}
      const actions = {}
      const getters = {}
      export default {
        state,
        mutations,
        actions,
        getters
      }
    2. 在index.js中处理
      import user from./modules/user
      const store = new Vuex.Store({
        modules: {
          user
        }
      }
    3. 使用
     尽管已经分模块了，但其实子模块的状态，还是会挂到根级别的 state 中，属性名就是模块名
     使用模块中的数据
      1. 直接通过模块名访问 $store.state.模块名.xxx
      2. 通过 mapstate
        映射默认根级别的映射 mapstate(['xxx'])
        子模块的映射 mapstate('模块名',['xxx'])- 需要开启命名空间
          export default {
            namespaced: true,   //开启命名空间
            state,
            mutations,
            actions,
            getters
          }
----------------------------------------------
目标:掌握模块中 getters 的访问语法
  使用模块中 getters 中的数据:
  1 直接通过模块名访问 $store.getters['模块名/xxx']
  2 通过 mapGetters 映射
    默认根级别的映射   mapGetters(['xxx'])
    子模块的映射      mapGetters('模块名', ['xxx']) 需要开启命名空间
----------------------------------------
目标:掌握模块中 mutation 的调用语法
  注意: 默认模块中的mutation和actions
  会被挂载到全局，需要开启命名空间，才会挂载到子模块
  1. 调用子模块中mutation:
    直接通过 store 调用 $store.commit('模块名/xxx' ，额外参数)
  2. 通过 mapMutations 映射
    默认根级别的映射   mapMutations(['xxx'])
    子模块的映射      mapMutations('模块名', ['xxx']) - 需要开启命名空间
-------------------------------------------------
目标:掌握模块中action 的调用语法(同理-直接类比 mutation 即可)
  注意:默认模块中的 mutation 和 actions 会被挂载到全局，需要开启命名空间，才会挂载到子模块。
  调用子模块中 action:
   1. 直接通过 store 调用 $store.dispatch(模块名/xxx，额外参数)
   2. 通过 maActions 映射
    默认根级别的映射 mapActions(['xxx'])
    子模块的映射 mapActions('模块名', ['xxx']')  需要开启命名空间
*/

// 导出给main.js使用
export default store
